#include "recordslamroute.h"

#include "ui_recordslamroute.h"

RecordSlamRoute::RecordSlamRoute(QWidget* parent) : QDialog(parent), ui(new Ui::RecordSlamRoute) {
  ui->setupUi(this);

  QTimer* timer500ms = new QTimer();
  connect(timer500ms, SIGNAL(timeout()), this, SLOT(slt50msTimer()));
  timer500ms->start(500);
  //  ui->lineEdit_route_num->setText("0");
  //  ui->lineEdit_route_fun->setText("0");
  //  ui->lineEdit_start->setText("0");
  //  ui->lineEdit_end->setText("0");
}

void RecordSlamRoute::showTips(const QString& str) {
  QString s = " " + QDateTime::currentDateTime().toString("hh:mm:ss ") + str;

  if (str.left(2) == QString("错误")) {
    ui->textBrowser->append("<font color=\"red\">" + s + "</font>");  // 换行添加字符
  } else {
    ui->textBrowser->append("<font color=\"blue\">" + s + "</font>");  // 换行添加字符
  }

  ui->textBrowser->moveCursor(QTextCursor::End);
}

RecordSlamRoute::~RecordSlamRoute() {
  if (routeFile != nullptr) {
    routeFile->flush();
    routeFile->close();
  }
  delete ui;
}

void RecordSlamRoute::keyPressEvent(QKeyEvent* e) { emit sigSendKyeEvent(e); }

void RecordSlamRoute::on_pushButton_close_clicked() { this->close(); }

#include "slamrouteplanning.h"

bool RecordSlamRoute::readPointData() {
  if (!PointInfolist.isEmpty()) { PointInfolist.clear(); }  //清空列表

  QString filename = "./slam-point/slam_point.csv";
  QFile SlamPointFile(filename);
  QStringList csvList;
  csvList.clear();

  if (!SlamPointFile.exists()) {
    showTips("错误，无法找到该文件:/slam-point/slam_point.csv");
    return false;
  }

  //对csv文件进行读写操作
  if (SlamPointFile.open(QIODevice::ReadWrite)) {
    QTextStream stream(&SlamPointFile);
    while (!stream.atEnd()) {
      csvList.push_back(stream.readLine().replace("\"", ""));  //保存到List当中
    }
    SlamPointFile.close();
  } else {
    showTips("错误，打开文件失败:/slam-point/slam_point.csv");
    return false;
  }

  //存到slam_point
  if (csvList.size() != 0) {
    //第0行
    QStringList valsplit0 = csvList.at(0).split(",");  //分隔字符串

    if (valsplit0.size() < 5) {
      showTips("第0行长度错误:slam_point.csv");
      return false;
    }

    if (valsplit0.at(0) != "id" || valsplit0.at(1) != "x" || valsplit0.at(2) != "y" || valsplit0.at(3) != "type" || valsplit0.at(4) != "child") {
      showTips("第0行格式错误:slam_point.csv");
      return false;
    }

    //第1行以下 标注id x  y  的内容
    for (int i = 1; i < csvList.size(); i++) {
      QStringList valsplit1 = csvList.at(i).split(",");  //分隔字符串
      PointInfo rpoint;
      rpoint.ID = valsplit1.at(0).toInt();
      rpoint.X = valsplit1.at(1).toInt();
      rpoint.Y = valsplit1.at(2).toInt();
      rpoint.Type = valsplit1.at(3).toInt();
      for (int i = 4; i < valsplit1.size(); i++) {
        if (valsplit1.at(i).trimmed().isEmpty()) { continue; }

        ID child;
        SlamRoutePlanning::RouteType type;
        SlamRoutePlanning::getIdAndRouteType(valsplit1.at(i), child, type);

        if (child <= 0) { continue; }

        rpoint.Childs.append(valsplit1.at(i).trimmed());
      }
      PointInfolist.append(rpoint);
    }
  }
  return true;
}

bool RecordSlamRoute::writeExitPointInfoList() {
  // foreach ( PointInfo demo, PointInfolist ) { showTips( QString( "befor id:%1 x:%2 y:%3" ).arg( demo.ID ).arg( demo.X ).arg( demo.Y ) ); }

  int id = ui->lineEdit_record_id->text().toInt();

  if (id < 0) {
    showTips("错误,ID参数设定不能少于0。");
    return false;
  }

  double shift = ui->lineEdit_shift->text().toDouble();  //退出点前移距离

  Point exit_point(static_cast<int>(cur_point.x() + shift * std::cos(cur_point.radian())),  //
                   static_cast<int>(cur_point.y() + shift * std::sin(cur_point.radian())),  //
                   cur_point.radian());

  showTips(QString("录制[id:%1]开始！").arg(id));
  if (id < PointInfolist.size()) {
    if (PointInfolist[id].X == 0.0 && PointInfolist[id].Y == 0.0) {  //原slampoint值为0,直接写入
      PointInfo rpoint;
      rpoint.ID = id;
      rpoint.X = exit_point.x();
      rpoint.Y = exit_point.y();
      rpoint.Type = 0;
      rpoint.Childs.clear();
      PointInfolist[id] = rpoint;
      writeToSlamPointCSV();  //写入
      showTips(QString("录制[id:%1 x:%2 y:%3]完成！").arg(id).arg(exit_point.x()).arg(exit_point.y()));
      return true;
    } else {
      int result = QMessageBox::question(nullptr, "询问", QString("原[id:%1 x:%2 y:%3]是否覆盖？").arg(id).arg(PointInfolist[id].X).arg(PointInfolist[id].Y), QMessageBox::Yes, QMessageBox::No, QMessageBox::NoButton);

      if (result == QMessageBox::Yes) {
        PointInfo rpoint;
        rpoint.ID = id;
        rpoint.X = exit_point.x();
        rpoint.Y = exit_point.y();
        rpoint.Type = 0;
        rpoint.Childs.clear();
        PointInfolist[id] = rpoint;
        writeToSlamPointCSV();  //写入
        showTips(QString("覆盖录制[id:%1 x:%2 y:%3]完成！").arg(id).arg(exit_point.x()).arg(exit_point.y()));
        return true;
      }
    }
  } else if (id == PointInfolist.size()) {
    PointInfo rpoint;
    rpoint.ID = id;
    rpoint.X = exit_point.x();
    rpoint.Y = exit_point.y();
    rpoint.Type = 0;
    rpoint.Childs.clear();
    PointInfolist.append(rpoint);
    writeToSlamPointCSV();  //写入
    showTips(QString("追加录制[id:%1 x:%2 y:%3]完成！").arg(id).arg(exit_point.x()).arg(exit_point.y()));
    return true;
  } else if (id > PointInfolist.size()) {
    PointInfo fpoint;
    for (int i = PointInfolist.size(); i < id; i++) {
      fpoint.X = 0;
      fpoint.Y = 0;
      fpoint.ID = i;
      fpoint.Type = 0;
      fpoint.Childs.clear();
      PointInfolist.append(fpoint);
    }
    fpoint.ID = id;
    fpoint.X = exit_point.x();
    fpoint.Y = exit_point.y();
    fpoint.Type = 0;
    fpoint.Childs.clear();
    PointInfolist.append(fpoint);
    writeToSlamPointCSV();  //写入
    showTips(QString("间隔追加录制[id:%1 x:%2 y:%3]完成！").arg(id).arg(exit_point.x()).arg(exit_point.y()));
    return true;
  }
  showTips(QString("录制[id:%1]取消！").arg(id));
  return false;
  // foreach ( PointInfo demo, PointInfolist ) { showTips( QString( "after id:%1 x:%2 y:%3" ).arg( demo.ID ).arg( demo.X ).arg( demo.Y ) ); }
}

bool RecordSlamRoute::writePointInfoList() {
  // foreach ( PointInfo demo, PointInfolist ) { showTips( QString( "befor id:%1 x:%2 y:%3" ).arg( demo.ID ).arg( demo.X ).arg( demo.Y ) ); }

  int id = ui->lineEdit_record_id->text().toInt();

  if (id < 0) {
    showTips("错误,ID参数设定不能少于0。");
    return false;
  }

  showTips(QString("录制[id:%1]开始！").arg(id));
  if (id < PointInfolist.size()) {
    if (PointInfolist[id].X == 0.0 && PointInfolist[id].Y == 0.0) {  //原slampoint值为0,直接写入
      PointInfo rpoint;
      rpoint.ID = id;
      rpoint.X = cur_point.x();
      rpoint.Y = cur_point.y();
      rpoint.Type = 0;
      rpoint.Childs.clear();
      PointInfolist[id] = rpoint;
      writeToSlamPointCSV();  //写入
      showTips(QString("录制[id:%1 x:%2 y:%3]完成！").arg(id).arg(cur_point.x()).arg(cur_point.y()));
      return true;
    } else {
      int result = QMessageBox::question(nullptr, "询问", QString("原[id:%1 x:%2 y:%3]是否覆盖？").arg(id).arg(PointInfolist[id].X).arg(PointInfolist[id].Y), QMessageBox::Yes, QMessageBox::No, QMessageBox::NoButton);

      if (result == QMessageBox::Yes) {
        PointInfo rpoint;
        rpoint.ID = id;
        rpoint.X = cur_point.x();
        rpoint.Y = cur_point.y();
        rpoint.Type = 0;
        rpoint.Childs.clear();
        PointInfolist[id] = rpoint;
        writeToSlamPointCSV();  //写入
        showTips(QString("覆盖录制[id:%1 x:%2 y:%3]完成！").arg(id).arg(cur_point.x()).arg(cur_point.y()));
        return true;
      }
    }
  } else if (id == PointInfolist.size()) {
    PointInfo rpoint;
    rpoint.ID = id;
    rpoint.X = cur_point.x();
    rpoint.Y = cur_point.y();
    rpoint.Type = 0;
    rpoint.Childs.clear();
    PointInfolist.append(rpoint);
    writeToSlamPointCSV();  //写入
    showTips(QString("追加录制[id:%1 x:%2 y:%3]完成！").arg(id).arg(cur_point.x()).arg(cur_point.y()));
    return true;
  } else if (id > PointInfolist.size()) {
    PointInfo fpoint;
    for (int i = PointInfolist.size(); i < id; i++) {
      fpoint.X = 0;
      fpoint.Y = 0;
      fpoint.ID = i;
      fpoint.Type = 0;
      fpoint.Childs.clear();
      PointInfolist.append(fpoint);
    }
    fpoint.ID = id;
    fpoint.X = cur_point.x();
    fpoint.Y = cur_point.y();
    fpoint.Type = 0;
    fpoint.Childs.clear();
    PointInfolist.append(fpoint);
    writeToSlamPointCSV();  //写入
    showTips(QString("间隔追加录制[id:%1 x:%2 y:%3]完成！").arg(id).arg(cur_point.x()).arg(cur_point.y()));
    return true;
  }
  showTips(QString("录制[id:%1]取消！").arg(id));
  return false;
  // foreach ( PointInfo demo, PointInfolist ) { showTips( QString( "after id:%1 x:%2 y:%3" ).arg( demo.ID ).arg( demo.X ).arg( demo.Y ) ); }
}

void RecordSlamRoute::writeToSlamPointCSV() {
  QString name = "./slam-point/slam_point.csv";
  QFile* slamPointFile = new QFile(name);
  slamPointFile->open(QIODevice::WriteOnly | QIODevice::Truncate);
  QTextStream route_text_stream(slamPointFile);

  route_text_stream << "id,x,y,type,child\r\n";

  for (const auto& point : PointInfolist) {
    route_text_stream << point.ID << "," << point.X << "," << point.Y << "," << point.Type;

    for (const auto& child : point.Childs) { route_text_stream << "," << child; }

    route_text_stream << "\r\n";
  }

  slamPointFile->close();
}

void RecordSlamRoute::on_pushButton_record_cur_point_clicked() {
  //获取现在slampoint信息
  if (!readPointData()) { return; }  //文件打开失败，直接退出
  if (writePointInfoList()) {        //改写slampointlist并且根据情况写入
    //写入成功，自动加一
    int id = ui->lineEdit_record_id->text().toInt();
    ui->lineEdit_record_id->setText(QString::number(id + 1));
  }
}

void RecordSlamRoute::on_pushButton_record_exit_point_clicked() {
  // 录制当前点往前n米的退出点

  //获取现在slampoint信息
  if (!readPointData()) { return; }  //文件打开失败，直接退出
  if (writeExitPointInfoList()) {    //改写slampointlist并且根据情况写入
    //写入成功，自动加一
    int id = ui->lineEdit_record_id->text().toInt();
    ui->lineEdit_record_id->setText(QString::number(id + 1));
  }
}

void RecordSlamRoute::on_pushButton_route_clicked() {
  int routeNum = ui->lineEdit_route_num->text().toInt();
  uint fun = ui->lineEdit_route_fun->text().toUInt();

  if (routeNum <= 0) {
    showTips("错误,路线参数设定错误。");
    return;
  }

  if (fun > 1) {
    showTips("错误,功能参数设定错误。");
    return;
  }

  QString routename = "./slam-route/" + QString::number(routeNum) + ".csv";
  routeFile = new QFile(routename);

  if (routeFile->exists()) {
    int result = QMessageBox::question(this, "路线文件已存在", "是否重新录制？", QMessageBox::Yes, QMessageBox::No, QMessageBox::Cancel);

    if (result == QMessageBox::Yes) {
      routeFile->remove();
      showTips(QString("删除文件：%1.csv").arg(routeNum));
      routeFile->setFileName(routename);
      showTips(QString("创建文件：%1.csv").arg(routeNum));
    } else if (result == QMessageBox::No) {
      showTips(QString("%1.csv文件追加录制").arg(routeNum));
    } else if (result == QMessageBox::Cancel) {
      return;
    }
  }

  routeFile->open(QIODevice::WriteOnly | QIODevice::Append);

  QTextStream route_text_stream(routeFile);
  if (routeFile->size() == 0) {  //新文件加首行
    route_text_stream << "routeNum"
                      << ","
                      << "fun"
                      << "\r\n";
    route_text_stream << routeNum << "," << fun << "\r\n";
    route_text_stream << "start"
                      << ","
                      << "end"
                      << ","
                      << "type"
                      << "\r\n";
  }
  is_open_record = true;
  showTips(QString("开始录制[%1:号线 %2:功能]").arg(routeNum).arg(fun));
  ui->lineEdit_route_num->setText(QString::number(routeNum + 1));
}

void RecordSlamRoute::slt50msTimer() {
  ui->label_time->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss "));
  ui->label_cur_point->setText(QString("x:%1 y:%2 ").arg(cur_point.x(), 0, 'f', 0).arg(cur_point.y(), 0, 'f', 0));
  ui->label_cur_point->setText(QString("(%1,%2,%3°)").arg(cur_point.x(), 0, 'f', 0).arg(cur_point.y(), 0, 'f', 0).arg(cur_point.radian() / M_PI * 180, 0, 'f', 0));
  ui->label_qrcode_cur_point->setText(QString("x:%1 y:%2  ").arg(qrcodePoint.x()).arg(qrcodePoint.y()));
  ui->label_qrcode_cur_id->setText(QString("rad:%1 ID:%2").arg(qrcodePoint.radian(), 0, 'f', 3).arg(qrcode_tag_id));
}

void RecordSlamRoute::sltRecvCurPoint(const int& x, const int& y, const double& radian) {
  cur_point.setX(x);
  cur_point.setY(y);
  cur_point.setRadian(radian);
}

void RecordSlamRoute::sltRecvQrcodePoint(const Point& qrcode, const int& id) {
  qrcodePoint = qrcode;
  qrcode_tag_id = id;
}

void RecordSlamRoute::on_pushButton_record_p2p_clicked() {
  if (!is_open_record) {
    showTips("错误，没打开录制");
    return;
  }

  uint type = 0;
  if (ui->radioButton_normal->isChecked()) {
    type = 0;
  } else if (ui->radioButton_enter->isChecked()) {
    type = 1;
  } else if (ui->radioButton_exit->isChecked()) {
    type = 2;
  }

  uint start = ui->lineEdit_start->text().toUInt();
  QString end = ui->lineEdit_end->text();  //.toUInt();

  QTextStream route_text_stream(routeFile);
  route_text_stream << start << "," << end << "," << type << ","
                    << "\r\n";
  showTips(QString("记录坐标[Start:%1 End:%2 Type:%3]").arg(start).arg(end).arg(type));
}

void RecordSlamRoute::on_pushButton_clear_msg_clicked() { ui->textBrowser->clear(); }

void RecordSlamRoute::on_pushButton_download_route_file_clicked() {}
